//////////////////////////////////////////////////////////////////////////////////////////////////////
// 项目名   : Container
// 文件名   : TestDeque.h
// 作者     : Aiye
// 日期     : 2025/9/1 15:31
// 邮箱     : 2878548868@qq.com
// 摘要     : 介绍deque容器
//////////////////////////////////////////////////////////////////////////////////////////////////////
#ifndef CONTAINER_TESTDEQUE_H
#define CONTAINER_TESTDEQUE_H
#include <deque>
#include <iostream>
#include <string>

#include "GlobalVariable.h"

class TestDeque
{
public:
    /**
     * @brief api接口与vector一致，只不过数据结构不同
     */
    static void TestConstuctor()
    {
        std::deque<int> nDeq{}; // 构造一个空双端队列
        std::deque<std::string> strDeq(2); // 构建一个两个元素得双端队列
        std::deque<int> nDeq2(2,3); // 构建一个包含3个元素得双端队列值都为3
        auto nDeq3 (nDeq2); // 深拷贝
        auto nDeq4 = std::move(nDeq2); // 移动资源
        std::deque<int> nDeq5{1,2,3,4,5}; // 初始化列表构造
        std::deque<int> nDeq6(nDeq5.begin() , nDeq5.end()); // 迭代器范围构造

        decltype(nDeq6)().swap(nDeq6); // 析构
    }

    /**
     * @brief 测试赋值操作
     */
    static void TestAssign()
    {
        // 基本与vector一致
        std::deque<std::string> strDeq{"Apple" , "Banana" ,"Cherry"};
        auto strDeq1 = strDeq; // 拷贝赋值深拷贝
        std::deque<std::string> strDeq2 = std::move(strDeq1); // 移动赋值拷贝
        decltype(strDeq) strDeq3{};
        strDeq3.assign(4,"Hello"); // assign函数赋值
        strDeq3.assign({"Aiye" , " Aice"}); // 直接替换容器的内容
    }

    /**
     * @brief 测试容量
     */
    static void TestCapacity()
    {
        std::deque<int> nDeq{1,2,3,4,5} ;
        std::cout << "Size:" << nDeq.size() << std::endl; // 获取元素数量
        std::cout << "Empty:" << nDeq.empty() << std::endl;; // 检查是否为空
        std::cout << "Max Size:" << nDeq.max_size() << std::endl; // 获取当前容器最大可以容纳的元素数量

        // 注意deque是没有capacity、reverse等操作的

    }

    /**
     * @brief 测试增删改查
     */
    static void TestCRUD()
    {
        { // 介绍增加操作
            std::deque<int> nDeq{2, 3, 4};

            // 在头部和尾部插入都非常高效
            nDeq.push_back(5);  // 尾部插入
            nDeq.push_front(1); // 头部插入

            std::deque<Person> perDeq{{"Alice", 18}};
            perDeq.push_back(Person("Bob", 22)); // 尾部构造临时对象再移动
            perDeq.push_front(Person("Eve", 21)); // 头部构造临时对象再移动

            // 就地构造，避免临时对象
            perDeq.emplace_back("Joker", 21); // 在尾部就地构造
            perDeq.emplace_front("Mario", 25); // 在头部就地构造

            auto it = nDeq.begin();
            nDeq.insert(it + 1, 0); // 在指定位置（第二个位置）插入，效率低于头尾插入
            nDeq.insert(nDeq.end(), 3, 20); // 在末尾插入3个20
            nDeq.emplace(it + 2, 99); // 在指定位置（第三个位置）就地构造插入
        }

        { // 介绍删除操作
            std::deque<int> nDeq{0, 1, 2, 3, 4, 5, 6};
            nDeq.pop_back(); // 尾部删除，高效
            nDeq.pop_front(); // 头部删除，高效

            auto it = nDeq.begin();
            nDeq.erase(it + 1); // 删除指定位置（第二个）的元素，效率低于头尾删除

            it = nDeq.begin(); // erase后迭代器可能失效，需要重新获取
            nDeq.erase(it, it + 2); // 删除一个区间的元素
            nDeq.clear(); // 清除所有元素
        }

        { // 介绍查操作
            std::deque<int> nDeq{1, 2, 3, 4, 5, 5, 6, 6};

            // [] 下标访问，不检查边界
            std::cout << "The second element is: " << nDeq[1] << std::endl;
            // nDeq[20]; // 越界访问，未定义行为

            // at() 成员函数，进行边界检查，越界抛出std::out_of_range异常
            for (size_t i = 0; i < nDeq.size(); ++i) {
                std::cout << "The element " << i << ": " << nDeq.at(i) << std::endl;
            }

            std::cout << "The first element is: " << nDeq.front() << std::endl;
            std::cout << "The last element is: " << nDeq.back() << std::endl;
        }

        { // 介绍修改的操作
            std::deque<int> nDeq{1, 2, 3, 4, 5, 6, 7, 8};

            nDeq[0] = 0; // 下标修改
            nDeq.at(1) = 1; // 安全的at()修改

            // deque没有直接的data()成员函数来获取指向所有数据的裸指针，
            // 因为它的元素不是存储在一个连续的数组中。

            // 迭代器遍历修改
            auto it = nDeq.begin();
            *(it + 2) = 2;

            auto rit = nDeq.rbegin();
            *rit = 77; // 修改最后一个数据

            for (int& elem : nDeq)
            {
                // 范围for引用修改
                if (elem > 2 && elem < 7)
                {
                    elem--;
                }
            }
        }
    }

};

#endif //CONTAINER_TESTDEQUE_H